`timescale 1ns / 1ps 
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/03/02 20:34:30
// Design Name:
// Module Name: sync_fifo
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module sync_fifo(clk,
                 resetb,
                 ie,
                 idat,
                 full,
                 oe,
                 odat,
                 empty

                );
parameter DW = 8;
parameter AW = 19;
parameter ADDR_TC = 640 * 480;
parameter DP = 1 << 19;
input clk;
input resetb;
input ie;
input [DW - 1: 0] idat;
output full;
input oe;
output [DW - 1: 0] odat;
output empty;
parameter ck2q = 1;
reg [AW - 1: 0] waddr;
wire [AW - 1: 0] waddr_p1 = waddr + 1'b1;
wire waddr_tc = (waddr == ADDR_TC);
always@(posedge clk or negedge resetb)
	begin
		if (!resetb)
			waddr <= #ck2q 0;
		else if (ie)
			begin
				if (waddr_tc)
					waddr <= #ck2q 0;
				else
					waddr <= #ck2q waddr_p1;
			end
	end
reg [AW - 1: 0] raddr;
wire [AW - 1: 0] raddr_p1 = raddr + 1'b1;
wire raddr_tc = (raddr == ADDR_TC);
always@(posedge clk or negedge resetb)
	begin
		if (!resetb)
			raddr <= #ck2q 0;
		else if (oe)
			begin
				if (raddr_tc)
					raddr <= #ck2q 0;
				else
					raddr <= #ck2q raddr_p1;
			end
	end
assign full = (waddr_p1 == raddr) | ((raddr == 0) & waddr_tc);
assign empty = (waddr == raddr);
reg [DW - 1: 0] buffer [0: ADDR_TC - 1];
always@(posedge clk)
	begin
		if (ie)
			buffer[waddr] <= #ck2q idat;
	end
reg [DW - 1: 0] odat;
always@(posedge clk)
	begin
		if (oe)
			odat <= buffer[raddr];
	end
endmodule
